﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Web;
using System.IO;
using System.Xml;
using System.Xml.Linq;

namespace Twite
{
    /// <summary>Twitterへのアクセスを提供する</summary>
    class AccessTwitter
    {
        #region 変数の定義
        private const string API = "http://twitter.com/";
        private const string SOURCE = "Twite";

        private NetworkCredential Credentials;
        #endregion

        #region コンストラクタ
        /// <summary>AccessTwitterのコンストラクタ</summary>
        /// <param name="userName">ユーザーID</param>
        /// <param name="password">パスワード</param>
        public AccessTwitter(string userName, string password)
        {
            Credentials = new NetworkCredential(userName, password);
        }
        #endregion
        
        #region GetTimeLine
        /// <summary>自分の friend の過去24時間以内に update されたステータスから最大20件を取得する。</summary>
        public XElement GetTimeLine()
        {
            string url = API + "statuses/friends_timeline.xml";

            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.Method = "POST";
            req.Credentials = Credentials;

            WebResponse responce;
            try
            {
                responce = req.GetResponse();
            }
            catch (WebException e)
            {
                throw (e);
            }

            return XElement.Load(XmlReader.Create(responce.GetResponseStream()));
        }

        /// <summary>自分の friend の過去24時間以内に update されたステータスから最大20件を取得する。</summary>
        /// <param name="page">ページ番号</param>
        public XElement GetTimeLine(int page)
        {
            string url = API + "statuses/friends_timeline.xml?page=" + page;

            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.Method = "POST";
            req.Credentials = Credentials;

            WebResponse responce;
            try
            {
                responce = req.GetResponse();
            }
            catch (WebException)
            {
                throw;
            }

            return XElement.Load(XmlReader.Create(responce.GetResponseStream()));
        }

        /// <summary>自分の friend の過去24時間以内に update されたステータスから最大20件を取得する。</summary>
        /// <param name="page">ページ番号</param>
        /// <param name="since">日時</param>
        public XElement GetTimeLine(int page, DateTime since)
        {
            string url = API + "statuses/friends_timeline.xml?page=" + page;

            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.Method = "POST";
            req.Credentials = Credentials;
            req.IfModifiedSince = since;

            WebResponse responce;
            try
            {
                responce = req.GetResponse();
            }
            catch(WebException e) {
                throw (e);
            }


            return XElement.Load(XmlReader.Create(responce.GetResponseStream()));
        }
        #endregion

        #region GetReplies
        /// <summary>自分に対する返信(冒頭が @ユーザ名 で始まるステータス)の一覧を取得する (最大20件)</summary>
        public XElement GetReplies()
        {
            string url = API + "statuses/replies.xml";

            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.Method = "POST";
            req.Credentials = Credentials;

            WebResponse responce;
            try
            {
                responce = req.GetResponse();
            }
            catch (WebException e)
            {
                throw (e);
            }

            return XElement.Load(XmlReader.Create(responce.GetResponseStream()));
        }

        /// <summary>自分に対する返信(冒頭が @ユーザ名 で始まるステータス)の一覧を取得する (最大20件)</summary>
        /// <param name="page">ページ番号</param>
        public XElement GetReplies(int page)
        {
            string url = API + "statuses/replies.xml?page=" + page;

            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.Method = "POST";
            req.Credentials = Credentials;

            WebResponse responce;
            try
            {
                responce = req.GetResponse();
            }
            catch (WebException e)
            {
                throw (e);
            }

            return XElement.Load(XmlReader.Create(responce.GetResponseStream()));
        }

        /// <summary>自分に対する返信(冒頭が @ユーザ名 で始まるステータス)の一覧を取得する (最大20件)</summary>
        /// <param name="page">ページ番号</param>
        /// <param name="since">日時</param>
        public XElement GetReplies(int page, DateTime since)
        {
            string url = API + "statuses/replies.xml?page=" + page;

            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.Method = "POST";
            req.Credentials = Credentials;
            req.IfModifiedSince = since;

            WebResponse responce;
            try
            {
                responce = req.GetResponse();
            }
            catch (WebException e)
            {
                throw (e);
            }

            return XElement.Load(XmlReader.Create(responce.GetResponseStream()));
        }
        #endregion

        /// <summary>自分のステータスを更新(update)する。</summary>
        /// <param name="status">ステータス</param>
        public XElement SendUpdate(string status)
        {
            string url = API + "statuses/update.xml";
            byte[] data = Encoding.ASCII.GetBytes(
                "status=" +
                HttpUtility.UrlEncode(status, Encoding.UTF8) + 
                "&source=" +
                HttpUtility.UrlEncode(SOURCE, Encoding.UTF8));

            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.Method = "POST";
            req.Credentials = Credentials;

            req.ContentType = "application/x-www-form-urlencoded";
            req.ContentLength = data.Length;

            req.ServicePoint.Expect100Continue = false;
            try
            {
                Stream reqStream = req.GetRequestStream();
                reqStream.Write(data, 0, data.Length);
                reqStream.Close();
            }
            catch (WebException)
            {
                throw;
            }

            WebResponse responce;
            try
            {
                responce = req.GetResponse();
            }
            catch (WebException)
            {
                throw;
            }

            return XElement.Load(XmlReader.Create(responce.GetResponseStream()));
        }
    }
}
